/*
 * Copyright  bocmbci
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import List from '@ohos.util.List';
import webview from '@ohos.web.webview';
import promptAction from '@ohos.promptAction';
import { CordovaBridge } from '../CordovaBridge';
import { CordovaInterface } from '../CordovaInterface';
import { CordovaPreferences } from '../CordovaPreferences';
import { CordovaResourceApi } from '../CordovaResourceApi';
import  { CordovaWebViewService}  from '../CordovaWebViewService';
import { NativeToJsMessageQueue } from '../NativeToJsMessageQueue';
import { PluginEntry } from '../PluginEntry';
import { PluginManager } from '../PluginManager';
import { PluginResult } from '../PluginResult';
import { SystemCookieManager } from './SystemCookieManager';
import { SystemExposedJsApi } from './SystemExposedJsApi';
import { KeyCode } from '@ohos.multimodalInput.keyCode';
import HashSet from '@ohos.util.HashSet';
import { Context } from '@ohos.abilityAccessCtrl';
import { KeyEvent } from '@ohos.multimodalInput.keyEvent';

export class SystemWebViewEngine implements CordovaWebViewService {
  cookieManager: SystemCookieManager;
  preferences: CordovaPreferences;
  bridge: CordovaBridge;
  cordova: CordovaInterface;
  pluginManager: PluginManager;
  resourceApi: CordovaResourceApi;
  nativeToJsMessageQueue: NativeToJsMessageQueue;

  boundKeyCodes = new HashSet<number>();

  context: Context;
  webviewController: webview.WebviewController;

  systemExposedJsApi: SystemExposedJsApi;

  constructor(context: Context, webviewController: webview.WebviewController) {
    this.context = context;
    this.webviewController = webviewController;
  }

  init(cordovaInterface: CordovaInterface, pluginEntries: List<PluginEntry>) {
    this.pluginManager = new PluginManager(this, cordovaInterface, Array.from(pluginEntries))

    this.nativeToJsMessageQueue = new NativeToJsMessageQueue(this.webviewController);

    this.bridge = new CordovaBridge(this.pluginManager, this.nativeToJsMessageQueue);

    this.systemExposedJsApi = new SystemExposedJsApi(this.bridge, this.webviewController);
  }

  getJsProxy(){
    return {
      object: this.systemExposedJsApi,
      name: '_cordovaNative',
      methodList: ['exec', 'setNativeToJsBridgeMode', 'retrieveJsMessages'],
      controller: this.webviewController
    }
  }

  isInitialized(): boolean {
    return true;
  }

  getViewController() {
    return this.webviewController;
  }

  onAlertCallBack(){
    return (event) => {
      //todo 第三个参数
      let handleResult: String = this.bridge.promptOnJsPrompt(event.url, event.message, event.message);
      if(handleResult && handleResult.trim().length > 0){
        event.result.handlePromptConfirm(handleResult);
        return true;
      }
      else{
        this.showMsg(event.message);
        return false;
      }
    }
  }

  onPromptCallBack(){
    return (event) => {
      //todo 第三个参数
      let handleResult: String = this.bridge.promptOnJsPrompt(event.url, event.message, event.message);
      if(handleResult && handleResult.trim().length > 0){
        event.result.handlePromptConfirm(handleResult);
        return true;
      }
      else{
        this.showMsg(event.message);
        return false;
      }
    }
  }

  onConfirmCallBack(){
    return (event?: {
      url: string;
      message: string;
      result: JsResult;
    }) => {
      AlertDialog.show({
        message: event.message,
        confirm: {
          value: '确认',
          action: () => {
            event.result.handleConfirm();
          }
        },
        cancel: () => {
          event.result.handleCancel();
        }
      });
      return true;
    }
  }

  onProgressChangedCallback(){
    return (event) => {
      if (event.newProgress === 100) {

      }
    }
  }

  loadUrlIntoView(url: string, recreatePlugins: boolean) {
    this.webviewController.loadUrl(url);
  }

  stopLoading(){
    this.webviewController.stop();
  }

  canGoBack(){
    return this.webviewController.accessBackward();
  }

  clearCache(){
    return this.webviewController.removeCache(true);
  }

  clearHistory(){
    return this.webviewController.clearHistory();
  }

  backHistory(){
    this.webviewController.backward();
    return true;
  }

  handlePause(keepRunning: boolean){
    if(!this.isInitialized()){
      return;
    }

    this.pluginManager.onPause(keepRunning);
    this.sendJavascript("pause");
  }


  handleResume(keepRunning: boolean){
    if(!this.isInitialized()){
      return;
    }

    this.pluginManager.onResume(keepRunning);
    this.sendJavascript("resume");
  }

  handleStart(){
    if(!this.isInitialized()){
      return;
    }
    this.pluginManager.onStart();
  }

  handleStop(){
    if(!this.isInitialized()){
      return;
    }
    this.pluginManager.onStop();
  }

  handleDestroy(){
    if(!this.isInitialized()){
      return;
    }
    this.pluginManager.onDestroy();
  }

  sendJavascript(statememt: string){
    this.nativeToJsMessageQueue.addJavaScript(statememt);
  }

  showWebPage(url: string, openExternal: boolean, clearHistory: boolean, params: Map<string, any>){
    if(clearHistory){
      this.clearHistory();
    }

    //openExternal逻辑暂不支持
    this.loadUrlIntoView(url, false);
  }

  setButtonPlumbedToJs(keyCode: number, isOverride: boolean){
    switch (keyCode) {
      case KeyCode.KEYCODE_VOLUME_UP:
      case KeyCode.KEYCODE_VOLUME_DOWN:
      case KeyCode.KEYCODE_BACK:
      case KeyCode.KEYCODE_MENU:
          if (isOverride) {
              this.boundKeyCodes.add(keyCode);
          } else {
              this.boundKeyCodes.remove(keyCode);
          }
          return;
      default:
        throw new Error("Unsupported keycode: " + keyCode);
    }
  }

  isButtonPlumbedToJs(keyCode: number){
    return this.boundKeyCodes.has(keyCode);
  }

  sendPluginResult(pluginResult: PluginResult, callbackId: string){
    this.nativeToJsMessageQueue.addPluginResult(pluginResult, callbackId);
  }

  getPluginManager(): PluginManager{
    return this.pluginManager;
  }

  getUrl(){
    return this.webviewController.getUrl();
  }

  getContext(){
    return this.context;
  }

  loadUrl(url: string){
    this.webviewController.loadUrl(url);
  }

  postMessage(id: string, data: any){
    this.pluginManager.postMessage(id, data);
  }

  onDispatchKeyEvent(event: KeyEvent){
    return true;
  }

  clearLoadTimeoutTimer(){

  }

  onPageStarted(newUrl: string){

  }

  onReceivedError(errorCode: number, description: string, failingUrl: string){

  }

  onPageFinishedLoading(url: string){

  }

  onNavigationAttempt(url: string){
    // Give plugins the chance to handle the url
    if (this.pluginManager.onOverrideUrlLoading(url)) {
      return true;
    } else if (this.pluginManager.shouldAllowNavigation(url)) {
      return false;
    } else if (this.pluginManager.shouldOpenExternalUrl(url)) {
      this.showWebPage(url, false, false, null);
      return true;
    }
    return true;
  }

  showMsg(msg){
    promptAction.showToast({
      message: msg,
      duration: 3000
    })
  }
}

